package cn.edu.tju.elm.service;

import cn.edu.tju.elm.model.Order;
import cn.edu.tju.elm.model.OrderDetailet;
import cn.edu.tju.elm.model.OrderStatus;
import cn.edu.tju.elm.model.Business;
import cn.edu.tju.elm.model.DeliveryAddress;
import cn.edu.tju.elm.model.Food;
import cn.edu.tju.elm.model.Cart;
import cn.edu.tju.elm.model.dto.OrderDTO;
import cn.edu.tju.elm.model.dto.OrderDetailetDTO;
import cn.edu.tju.core.model.User;
import cn.edu.tju.elm.repository.OrderRepository;
import cn.edu.tju.elm.repository.BusinessRepository;
import cn.edu.tju.elm.repository.AddressRepository;
import cn.edu.tju.elm.repository.FoodRepository;
import cn.edu.tju.elm.repository.OrderDetailetRepository;
import cn.edu.tju.elm.repository.CartRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.ArrayList;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private BusinessRepository businessRepository;
    
    @Autowired
    private AddressRepository addressRepository;
    
    @Autowired
    private FoodRepository foodRepository;
    
    @Autowired
    private OrderDetailetRepository orderDetailetRepository;
    
    @Autowired
    private CartRepository cartRepository;
    
    @Override
    @Transactional
    public Order createOrder(Order order, User currentUser) {
        // 第一步：验证商家是否存在
        Long businessId = order.getBusiness().getId();
        Business business = businessRepository.findById(businessId)
                .orElseThrow(() -> new RuntimeException("商家不存在，ID: " + businessId));
        order.setBusiness(business);
        
        // 第二步：验证配送地址是否存在
        Long addressId = order.getDeliveryAddress().getId();
        DeliveryAddress deliveryAddress = addressRepository.findById(addressId)
                .orElseThrow(() -> new RuntimeException("配送地址不存在，ID: " + addressId));
        order.setDeliveryAddress(deliveryAddress);
        
        // 第三步：设置订单创建信息
        LocalDateTime now = LocalDateTime.now();
        order.setCreator(currentUser.getId());
        order.setCreateTime(now);
        order.setUpdater(currentUser.getId());
        order.setUpdateTime(now);
        order.setDeleted(false);
        
        // 第四步：设置订单所属用户
        order.setCustomer(currentUser);
        
        // 第五步：设置订单日期极为当前时间
        order.setOrderDate(now);
        
        // 第六步：设置默认订单状态为"待支付"
        if (order.getOrderState() == null) {
            order.setOrderState(OrderStatus.PENDING_PAYMENT.getValue());
        }
        
        // 第七步：从购物车获取商品并创建订单明细
        createOrderDetailsFromCart(order, currentUser, business);
        
        // 第八步：计算订单总额
        order.setOrderTotal(order.calculateTotal());
        
        // 第九步：保存订单（级联保存订单明细）
        Order savedOrder = orderRepository.save(order);
        
        // 第十步：清空购物车中对应的商品
        clearCartItems(currentUser, business);
        
        return savedOrder;
    }
    
    /**
     * 从购物车获取商品并创建订单明细
     */
    private void createOrderDetailsFromCart(Order order, User currentUser, Business business) {
        // 获取用户购物车中该商家的所有商品
        List<Cart> cartItems = cartRepository.findByCustomerAndBusiness(currentUser, business);
        
        if (cartItems == null || cartItems.isEmpty()) {
            throw new RuntimeException("购物车中没有该商家的商品");
        }
        
        // 创建订单明细列表
        List<OrderDetailet> orderDetailets = new ArrayList<>();
        
        // 将购物车商品转换为订单明细
        for (Cart cartItem : cartItems) {
            OrderDetailet detail = new OrderDetailet();
            detail.setFood(cartItem.getFood());
            detail.setQuantity(cartItem.getQuantity());
            
            // 使用OrderDetailet的setFood方法会自动设置itemPrice
            // detail.setFood()方法会自动设置itemPrice为食品的价格
            
            // 设置订单关联
            detail.setOrder(order);
            
            // 设置创建和更新信息
            detail.setCreator(order.getCreator());
            detail.setCreateTime(order.getCreateTime());
            detail.setUpdater(order.getUpdater());
            detail.setUpdateTime(order.getUpdateTime());
            detail.setDeleted(false);
            
            orderDetailets.add(detail);
        }
        
        // 设置订单明细
        order.setOrderDetailets(orderDetailets);
    }
    
    /**
     * 清空购物车中对应的商品
     */
    private void clearCartItems(User currentUser, Business business) {
        List<Cart> cartItems = cartRepository.findByCustomerAndBusiness(currentUser, business);
        cartRepository.deleteAll(cartItems);
    }
    
    
    
    @Override
    @Transactional
    public void deleteOrder(Long id, User currentUser) {
        // 修改：使用新的查询方法，只查找未删除的订单
        Optional<Order> orderOpt = orderRepository.findByIdAndDeletedIsFalse(id);
        if (orderOpt.isPresent()) {
            Order order = orderOpt.get();
            
            // 权限验证
            if (!order.getCustomer().getId().equals(currentUser.getId())) {
                throw new RuntimeException("无权删除此订单");
            }
            
            // 使用枚举进行状态验证
            if (!order.canBeDeleted()) {
                throw new RuntimeException("当前订单状态(" + 
                    order.getOrderStateDisplay() + 
                    ")不允许删除，只能删除待支付或已取消的订单");
            }
            
            // 软删除订单
            order.setDeleted(true);
            order.setUpdater(currentUser.getId());
            order.setUpdateTime(LocalDateTime.now());
            orderRepository.save(order);
        } else {
            throw new RuntimeException("订单不存在");
        }
    }
    
    @Override
    public Optional<Order> findById(Long id) {
        // 修改：使用新的查询方法，只查找未删除的订单
        return orderRepository.findByIdAndDeletedIsFalse(id);
    }
    
    @Override
    public List<Order> findByCustomer(User customer) {
        return orderRepository.findByCustomer(customer);
    }
    
    @Override
    public List<Order> findByCustomerId(Long customerId) {
        return orderRepository.findByCustomerId(customerId);
    }
    
    @Override
    public Optional<Order> findByIdAndCustomer(Long id, User customer) {
        return orderRepository.findByIdAndCustomer(id, customer);
    }
    
    // 新增方法：按商家查询订单
    @Override
    public List<Order> findByBusiness(Business business) {
        return orderRepository.findByBusiness(business);
    }
    
    // 新增方法：按状态查询订单
    @Override
    public List<Order> findByOrderState(OrderStatus orderStatus) {
        return orderRepository.findByOrderState(orderStatus.getValue());
    }
    
    // 新增方法：更新订单状态
    @Override
    @Transactional
    public Order updateOrderState(Long id, OrderStatus orderState, User currentUser) {
        // 修改：使用新的查询方法，只查找未删除的订单
        Optional<Order> orderOpt = orderRepository.findByIdAndDeletedIsFalse(id);
        if (orderOpt.isPresent()) {
            Order order = orderOpt.get();
            
            // 权限验证
            if (!order.getCustomer().getId().equals(currentUser.getId())) {
                throw new RuntimeException("无权修改此订单状态");
            }
            
            // 更新状态
            order.setOrderState(orderState.getValue());
            order.setUpdater(currentUser.getId());
            order.setUpdateTime(LocalDateTime.now());
            
            return orderRepository.save(order);
        }
        throw new RuntimeException("订单不存在");
    }
    
    // 新增方法：获取订单详情（包含明细和食品信息）
    @Override
    @Transactional(readOnly = true)
    public Order getOrderByIdWithDetails(Long id, User currentUser) {
        // 使用Fetch Join一次性加载订单明细和食品信息
        Optional<Order> orderOpt = orderRepository.findByIdAndCustomerWithDetails(id, currentUser);
        
        if (orderOpt.isPresent()) {
            return orderOpt.get();
        }
        
        // 如果订单不存在或用户无权访问，返回null
        return null;
    }
    
    // 新增方法：获取订单DTO
    @Override
    @Transactional(readOnly = true)
    public OrderDTO getOrderDTOById(Long id, User currentUser) {
        // 使用Fetch Join一次性加载所有关联信息
        Optional<Order> orderOpt = orderRepository.findByIdAndCustomerWithDetails(id, currentUser);
        
        if (orderOpt.isPresent()) {
            Order order = orderOpt.get();
            return convertToDTO(order);
        }
        
        // 如果订单不存在或用户无权访问，返回null
        return null;
    }
    
    /**
     * 将Order实体转换为OrderDTO
     */
    private OrderDTO convertToDTO(Order order) {
        OrderDTO dto = new OrderDTO();
        
        dto.setId(order.getId());
        dto.setOrderDate(order.getOrderDate());
        dto.setOrderTotal(order.getOrderTotal());
        dto.setOrderState(order.getOrderState());
        dto.setOrderStateDisplay(order.getOrderStateDisplay());
        
        // 设置客户信息
        if (order.getCustomer() != null) {
            dto.setCustomerId(order.getCustomer().getId());
            dto.setCustomerName(order.getCustomer().getUsername()); // 使用getUsername()方法
        }
        
        // 设置商家信息
        if (order.getBusiness() != null) {
            dto.setBusinessId(order.getBusiness().getId());
            dto.setBusinessName(order.getBusiness().getBusinessName()); // 使用极getBusinessName()方法
        }
        
        // 设置地址信息
        if (order.getDeliveryAddress() != null) {
            dto.setAddressId(order.getDeliveryAddress().getId());
            dto.setAddressDetail(order.getDeliveryAddress().getAddress()); // 使用getAddress()方法
        }
        
        // 转换订单明细
        if (order.getOrderDetailets() != null && !order.getOrderDetailets().isEmpty()) {
            List<OrderDetailetDTO> detailetDTOs = order.getOrderDetailets().stream()
                .map(this::convertDetailetToDTO)
                .collect(Collectors.toList());
            dto.setOrderDetailets(detailetDTOs);
        }
        
        return dto;
    }
    
    /**
     * 将OrderDetailet实体转换为OrderDetailetDTO
     */
    private OrderDetailetDTO convertDetailetToDTO(OrderDetailet detailet) {
        OrderDetailetDTO dto = new OrderDetailetDTO();
        
        dto.setId(detailet.getId());
        dto.setQuantity(detailet.getQuantity());
        dto.setItemPrice(detailet.getItemPrice());
        dto.setItemTotal(detailet.calculateItemTotal());
        
        // 设置食品信息
        if (detailet.getFood() != null) {
            dto.setFoodId(detailet.getFood().getId());
            dto.setFoodName(detailet.getFood().getFoodName()); // 使用getFoodName()方法
        }
        
        return dto;
    }
    
    
    @Override
    @Transactional
    public Order simulatePayment(Long orderId, User currentUser) {
        // 修改：使用新的查询方法，只查找未删除的订单
        Optional<Order> orderOpt = orderRepository.findByIdAndDeletedIsFalse(orderId);
        if (!orderOpt.isPresent()) {
            throw new RuntimeException("订单不存在，ID: " + orderId);
        }
        Order order = orderOpt.get();

        // 2. 权限校验：确保当前用户是订单的拥有者
        if (!order.getCustomer().getId().equals(currentUser.getId())) {
            throw new RuntimeException("无权操作此订单");
        }

        // 3. 状态校验：确保订单当前处于"待支付"状态
        if (order.getOrderState() != OrderStatus.PENDING_PAYMENT.getValue()) {
            throw new RuntimeException("订单当前状态不允许支付，当前状态: " + order.getOrderStateDisplay());
        }

        // 4. 核心：执行所有支付成功后的业务逻辑
        // 4.1 更新订单状态为"已支付"
        order.setOrderState(OrderStatus.PAID.getValue());
        
        // 4.2 更新订单的更新时间和其他审计字段（重要！）
        order.setUpdater(currentUser.getId());
        order.setUpdateTime(LocalDateTime.now());
        
        // 4.3 【可选但重要】这里可以调用支付成功后的其他方法
        // 例如：扣除库存、发送支付成功通知等
        // this.processPostPaymentActions(order); 

        // 5. 保存并返回更新后的订单
        return orderRepository.save(order);
    }
}